package com.example.foo.p.service;

import java.math.BigDecimal;
import java.util.List;
import java.util.function.Function;

import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.transaction.annotation.Transactional;

import com.example.foo.account.AccountException;
import com.example.foo.account.model.Account;
import com.example.foo.account.service.AccountService;
import com.example.foo.ftt.FttUserException;
import com.example.foo.ftt.FttUserHelper;
import com.example.foo.ftt.model.FttUser;
import com.example.foo.ftt.service.FttUserService;
import com.example.foo.member.WithdrawException;
import com.example.foo.member.model.MemberBankcard;
import com.example.foo.member.model.MemberIdcard;
import com.example.foo.member.service.MemberBankcardService;
import com.example.foo.member.service.MemberIdcardService;
import com.example.foo.member.service.WithdrawService;
import com.example.foo.user.UserException;
import com.example.foo.user.model.User;
import com.example.foo.user.service.UserService;

@org.springframework.stereotype.Service
public class FttRegisterService {

	private final UserService userService;
	private final FttUserService fttUserService;
	private final AccountService accountService;
	private final MemberIdcardService memberIdcardService;
	private final MemberBankcardService memberBankcardService;
	private final WithdrawService withdrawService;

	public FttRegisterService(UserService userService,
			FttUserService fttUserService,
			AccountService accountService,
			MemberIdcardService memberIdcardService,
			MemberBankcardService memberBankcardService,
			WithdrawService withdrawService) {
		this.userService = userService;
		this.fttUserService = fttUserService;
		this.accountService = accountService;
		this.memberIdcardService = memberIdcardService;
		this.memberBankcardService = memberBankcardService;
		this.withdrawService = withdrawService;
	}

	// ========== Register ==========

	public User createUserRegisterByCellphone(String cellphone) {
		String name = "";
		String avatar = "";
		String wxUnionid = "";
		String wxJson = "";
		Long hjyUserId = 0L;
		return createUserRegister(cellphone, name, avatar, wxUnionid, wxJson, hjyUserId);
	}

	public User createUserRegister(String cellphone, String name, String avatar, String wxUnionid, String wxJson, Long hjyUserId) {
		User user = userService.createUser(cellphone, name, avatar, wxUnionid, wxJson, hjyUserId);
		return user;
	}

	@Transactional(timeout = 60, rollbackFor = Exception.class)
	public FttUser createFttUserRegisterByCellphone(String cellphone, FttUser referralParentFttUser) {
		User user = userService.findUserByCellphone(cellphone);
		if (user == null) {
			user = createUserRegisterByCellphone(cellphone);
		}
		Long userId = user.getId();

		Long referralParentUserId = referralParentFttUser.getUserId();
		String referralParentUserIdPath = FttUserHelper.referralParentUserIdPath(referralParentFttUser);
		String referralCode = randomNumeric(6, 15, val -> fttUserService.findFttUserCountExistByReferralCode(val));

		FttUser fttUser = fttUserService.createFttUser(cellphone, referralCode, referralParentUserId, referralParentUserIdPath, userId);
		memberIdcardService.createMemberIdcardPending(userId);
		accountService.createAccounts(userId);

		return fttUser;
	}

	@Transactional(timeout = 60, rollbackFor = Exception.class)
	public void updateFttUserCellphone(Long id, String cellphone) {
		if (userService.findUserByCellphone(cellphone) != null) {
			throw new UserException(String.format("用户%s已存在", cellphone));
		}
		if (fttUserService.findFttUserByCellphone(cellphone) != null) {
			throw new FttUserException(String.format("网体用户%s已存在", cellphone));
		}
		FttUser fttUser = fttUserService.findFttUserById(id);
		Long userId = fttUser.getUserId();
		MemberIdcard memberIdcard = memberIdcardService.findMemberIdcardByUserId(userId);
		userService.updateUserCellphone(userId, cellphone);
		fttUserService.updateFttUserCellphone(fttUser.getId(), cellphone);
		memberIdcardService.updateMemberIdcardCellphone(memberIdcard.getId(), cellphone);
	}

	@Transactional(timeout = 60, rollbackFor = Exception.class)
	public void deleteFttUserCascadeById(Long id) {
		FttUser fttUser = fttUserService.findFttUserById(id);
		Long userId = fttUser.getUserId();

		//
		if (fttUserService.findFttUserCountByReferralParentUserId(userId) > 0) {
			throw new FttUserException("已有推荐下级用户");
		}
		if (fttUserService.findFttUserCountByParentUserId(userId) > 0) {
			throw new FttUserException("已有网体下级用户");
		}

		List<Account> accounts = accountService.findAccountsByUserId(userId);
		for (Account account : accounts) {
			if (account.getTotal().compareTo(BigDecimal.ZERO) > 0) {
				throw new AccountException("已有账户变动");
			}
		}

		if (accountService.findAccountItemCountExistByUserId(userId)) {
			throw new AccountException("已有账户流水");
		}

		if (withdrawService.findWithdrawCountExistByUserId(userId)) {
			throw new WithdrawException("已有提现单");
		}

		//
		fttUserService.deleteFttUserById(fttUser.getId());

		for (Account account : accounts) {
			accountService.deleteAccountById(account.getId());
		}

		MemberIdcard memberIdcard = memberIdcardService.findMemberIdcardByUserId(userId);
		memberIdcardService.deleteMemberIdcardById(memberIdcard.getId());

		List<MemberBankcard> memberBankcards = memberBankcardService.findMemberBankcardsByUserId(userId);
		for (MemberBankcard memberBankcard : memberBankcards) {
			memberBankcardService.deleteMemberBankcardById(memberBankcard.getId());
		}
	}

	public static String randomNumeric(int length, int maxFailure, Function<String, Boolean> function) {
		for (int i = 0; i < maxFailure; i++) {
			String val = RandomStringUtils.randomNumeric(length);
			if (!function.apply(val)) {
				return val;
			}
		}
		throw new IllegalStateException("生成唯一值尝试次数太多");
	}

}
